#include "res/res_texture_mgr.h"
#include "res/res_font.h"

#include "tex/tex_bitmap.h"
#include "tex/tex_bmp.h"
#include "frame.h"
#include "render/r_frustum.h"
#include "file/f_stream.h"
#include "file/f_filehandler.h"
#include "file/f_absfs.h"
#include "material.h"
#include "timer.h"
#include "log.h"

#include "color.h"
#include "text.h"

#include "gui/gui.h"
#include "gui/gui_stats.h"
#include "gui/gui_profiler.h"

#include <boost/signal.hpp>
#include <vector>

G3::FONT Font1;
G3::FILESTREAM Stream;

G3::FRAME frame (640, 480, 24, 0);

G3::FPS_COUNTER FPSCounter;
G3::TIMER MovementTimer;
G3::GUI::LABEL l1, l2;
G3::GUI::GROUP g1;
G3::GUI::BUTTON b1;
G3::GUI::SCROLLBAR sb1;

void OnButton1Clicked (G3::INPUT *aInput, G3::GUI::WIDGET *aWidget) {
	Assert (aInput, "OnButton1Clicked: aInput argument is a NULL pointer");
	Assert (aWidget, "OnButton1Clicked: aWidget argument is a NULL pointer");
	
	l2.Print ("Button Clicked");
}

void OnButton1Over (G3::INPUT *aInput, G3::GUI::WIDGET *aWidget) {
	Assert (aInput, "OnButton1Over: aInput argument is a NULL pointer");
	Assert (aWidget, "OnButton1Over: aWidget argument is a NULL pointer");
	
	l2.Print ("Button Over");
}

void OnButton1Out (G3::INPUT *aInput, G3::GUI::WIDGET *aWidget) {
	Assert (aInput, "OnButton1Out: aInput argument is a NULL pointer");
	Assert (aWidget, "OnButton1Out: aWidget argument is a NULL pointer");
	
	l2.Print ("Button Out");
}

void GUIUpdateHandler (G3::INPUT *Input, float aElapsedTime) {
	G3::GUI::PROFILER prof ("UpdateHandler");

	if (Input->Keyboard.IsKeyDown (SDLK_a))
		Input->Frame->Renderer.Camera.Move (G3::VEC3F (0.0f, 1.0f, 0.0f) * aElapsedTime);
	if (Input->Keyboard.IsKeyDown (SDLK_z))
		Input->Frame->Renderer.Camera.Move (G3::VEC3F (0.0f, -1.0f, 0.0f) * aElapsedTime);
	if (Input->Keyboard.IsKeyDown (SDLK_LEFT))
		Input->Frame->Renderer.Camera.Move (G3::VEC3F (-1.0f, 0.0f, 0.0f) * aElapsedTime);
	if (Input->Keyboard.IsKeyDown (SDLK_RIGHT))
		Input->Frame->Renderer.Camera.Move (G3::VEC3F (1.0f, 0.0f, 0.0f) * aElapsedTime);
	if (Input->Keyboard.IsKeyDown (SDLK_UP))
		Input->Frame->Renderer.Camera.Move (G3::VEC3F (0.0f, 0.0f, 1.0f) * aElapsedTime);
	if (Input->Keyboard.IsKeyDown (SDLK_DOWN))
		Input->Frame->Renderer.Camera.Move (G3::VEC3F (0.0f, 0.0f,-1.0f) * aElapsedTime);
	
	if (Input->Keyboard.IsKeyDown (SDLK_ESCAPE))
		Input->SendQuit ();
}

int main (int argc, char **argv) {
	frame.Create ("Game3ngine");

	frame.Renderer.Create ();
	frame.Renderer.SetPerspective (640, 480);
	
	frame.Input.Mouse.SetMode (MOUSE_NORMAL);
	
	frame.Input.doOnUpdate (GUIUpdateHandler);

    /* Enable smooth shading */
    glShadeModel( GL_SMOOTH );

    /* Set the background black */
    glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );

    /* Depth buffer setup */
    glClearDepth( 1.0f );

    /* The Type Of Depth Test To Do */
    glDepthFunc( GL_LEQUAL );

    /* Enable 2D Texture Mapping */
    glEnable( GL_TEXTURE_2D );
	
	G3::MainFilesys.MountDir ("../../media/font", "");
	
	Font1.Load ("font.lua");

	l1.AttachFont (&Font1);
	l2.AttachFont (&Font1);

	l1.SetPosition (G3::VEC2I (10, 10));
	
	l2.Print ("Ajou, ma siia kirjutan..");
	
	g1.AttachFont (&Font1);
	g1.SetCaption ("Group 1");
	g1.SetRect (G3::RECTI (50, 30, 200, 100));

	b1.Create (G3::RECTI (52, 40, 52, 40), &Font1, "Button 1");
	b1.doOnMouseClicked (OnButton1Clicked);
	b1.doOnMouseOver (OnButton1Over);
	b1.doOnMouseOut (OnButton1Out);

	sb1.SetDimensions (300, 10);
	sb1.SetPosition (G3::VEC2I (50, 300));
	sb1.SetButtonDimensions (10, 10);
	sb1.SetAttribs (10, 1, 0);
	
	G3::GUI::MainGui.Root.Rect = G3::RECTI (0, 0, 640, 480);
	G3::GUI::MainGui.AddWidget (NULL, &l1);
	G3::GUI::MainGui.AddWidget (NULL, &l2);
	G3::GUI::MainGui.AddWidget (NULL, &g1);
	G3::GUI::MainGui.AddWidget (NULL, &b1);
	G3::GUI::MainGui.AddWidget (NULL, &sb1);
	
	g1.Hide ();

	G3::GUI::MainProfilerMgr.AddStatsPage (&Font1, G3::RECTI (3, 100, 637, 270));

	// Attach the GUI an input handler
	G3::GUI::MainGui.AttachInput (&frame.Input);
	
	FPSCounter.Start ();
	MovementTimer.Start ();
	
	while (true) {
		G3::GUI::PROFILER *prof = new G3::GUI::PROFILER ("MainLoop");

		frame.Input.GetInput ();

        frame.Renderer.ClearBuffer ();
		
		FPSCounter.CheckTime ();
		
	    frame.Renderer.Look ();
            frame.Renderer.RenderGrid ();
		
		l1.Print ("FPS: %lf Scrollbar: %d/%d", FPSCounter.FPS, sb1.GetViewPosition (), sb1.TotalSize);
		
		G3::GUI::MainGui.Draw (0.0f);
		
        frame.Renderer.SwapBuffer ();
		
		FPSCounter.AddFrame ();

		delete prof;
	}

	Font1.Clear ();

	return 0;
}
